Android Patch实践
常见的热补丁方案
- Dexposed 方法级别的热修复:对Android系统版本,虚拟机类型有一定限制
- Andfix 方法级别特修:没有深入了解,jni的方案,应该也是存在兼容性问题
- 腾讯类替换方案,类级别的方案 : 缺点,需要应用重启
我们采用的方案——AspectJ切面编程
AOP切面编程
面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。基本上可以简单理解为将执行过程进行切片,可以在切点处做一些相关逻辑处理。
最常见的gradle也是支持切面编程的,例如:我们可以在某一个Task的前后做一些事情。
关于AspectJ
aop并不是一个新技术,而是比较成熟的一门技术了。但是它大多的应用场景在Java EE方面。比如各大成熟的web框架都支持aop的编程,spring自带又aop的框架,但不是aspectJ,但是由于aspectJ 1.5之后对Java的兼容性堪称完美至极,所以大部分开发者都把aspectJ应用到了spring上。
AspectJ具体可以看什么事情
aspectJ是一个非常强大的aop变成框架,
原理
与Dexposed基本相同,都是采用了AOP的方案,只不过是是实现原理不同。简单来讲就是实现对方法调用的hook,当方法调用时可以监听到,从而可以在方法调用前后做一些事情,或者直接替换掉该方法。
阿里选择Dexposed方案的原因
阿里当初做热补丁方案的时候,也曾经考虑首选aspectJ方法,但是它没有选择aspectJ方案的原因是,由于阿里有一些特殊的需求:就是需要对android系统很多类的调用做切面化分析。比如:分析Android系统某个类各方法的调用。这种需求AspectJ是不能满足的,因此阿里后来选择了Dexposed的方案。
AspectJ方案的优缺点
网易新闻的方案:不存在Android兼容性问题,完全基于java的方案。
缺点:
1. 编译效率有影响--解决方法
2. 执行效率与patch包大小有关,涉及到反射,反射是不可避免的,包括其他方案也或多或少的涉及到反射。但是对于bug修复来说,代码量很小,反射的效率基本可以忽略。
难点
- 加载patch类和patch方法的问题
解决方案:将patch类打包成jar或者apk,即我们可以通过现有api进行加载的方式,保证patch类可以在运行时进行加载 - 动态调用patch方法问题以及当前需要patch类对象的获取
aspectJ变成中提供了现有api可以获取当前运行对象,然后结合反射,强行注入patch类 - 代码混淆问题
解决方案有多重:- 脚本方案
- android gradle插件1.5之后引入的transform API方案
- 由于混淆导致的ClassNotFound,以及解决方案
具体代码分析
反编译分析,理解AspectJ
如何进行打补丁
后续安排
- 开源
- 编写gradle插件,方便移植和解耦
私下交流
blog: www.glanwang.com
pop: bjwangguangcong
微信:13241901436